<?php


namespace support\command\workerman;

use Webman\Config;
use Dotenv\Dotenv;
use Workerman\Worker;
use support\command\workerman\Worker as W;
use Workerman\Connection\TcpConnection;
use support\bootstrap\Container;
use support\Request;
use support\bootstrap\Log;
use Webman\App;
use Webman\Route;
use Webman\Middleware;
use Workerman\Protocols\Http;

class HttpWorker implements W
{
    protected $config = null;

    public function register()
    {
        $this->config = config('server');
        $this->initWorker();
        $this->createWorker();
    }

    protected function initWorker()
    {
        Worker::$onMasterReload = function (){
            if (function_exists('opcache_get_status')) {
                if ($status = opcache_get_status()) {
                    if (isset($status['scripts']) && $scripts = $status['scripts']) {
                        foreach (array_keys($scripts) as $file) {
                            opcache_invalidate($file, true);
                        }
                    }
                }
            }
        };
        Worker::$pidFile                      = $this->config['pid_file'];
        Worker::$stdoutFile                   = $this->config['stdout_file'];
        TcpConnection::$defaultMaxPackageSize = $config['max_package_size'] ?? 10*1024*1024;
    }

    protected function createWorker()
    {
        $worker = new Worker($this->config['listen'], $this->config['context']);
        $property_map = [
            'name',
            'count',
            'user',
            'group',
            'reusePort',
            'transport',
        ];
        foreach ($property_map as $property) {
            if (isset($this->config[$property])) {
                $worker->$property = $this->config[$property];
            }
        }
        $worker->onWorkerStart = function ($worker) {
            set_error_handler(function ($level, $message, $file = '', $line = 0, $context = []) {
                if (error_reporting() & $level) {
                    throw new \ErrorException($message, 0, $level, $file, $line);
                }
            });
            register_shutdown_function(function ($start_time) {
                if (time() - $start_time <= 1) {
                    sleep(1);
                }
            }, time());
            foreach (config('autoload.files', []) as $file) {
                include_once $file;
            }
            if (method_exists('Dotenv\Dotenv', 'createUnsafeImmutable')) {
                Dotenv::createUnsafeImmutable(base_path())->load();
            } else {
                Dotenv::createMutable(base_path())->load();
            }
            Config::reload(config_path(), ['route', 'container']);
            foreach (config('bootstrap', []) as $class_name) {
                /** @var \Webman\Bootstrap $class_name */
                $class_name::start($worker);
            }
            $app = new App($worker, Container::instance(), Log::channel('default'), app_path(), public_path());
            Route::load(config_path() . '/route.php');
            Middleware::load(config('middleware', []));
            Middleware::load(['__static__' => config('static.middleware', [])]);
            Http::requestClass(Request::class);
            $worker->onMessage = [$app, 'onMessage'];
        };
    }
}
